//#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#* DtRecord.h *#*#*#*#*#*#*#*#* (C) 2000-2024 DekTec
//

#ifndef __DTRECORD_H
#define __DTRECORD_H

//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- Include files -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
#include <stdarg.h>


// Windows/Microsoft uses with _ => Linux uses without
#ifndef WIN32
#define _vsnprintf vsnprintf
#endif

//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- class Exc -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
//
class Exc
{
public:
    Exc( const char* pFormat, ...  )
    {
        va_list  ArgList;
        va_start(ArgList, pFormat);
        _vsnprintf(m_ErrorMsg, sizeof(m_ErrorMsg)-1, pFormat, ArgList);
        va_end(ArgList);
    };
    virtual ~Exc() {};

    operator const char* () const { return m_ErrorMsg; }

protected:

    // Error message
    char m_ErrorMsg[1024];
};
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- PCAP -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
#define PCAP_MAGIC_NUMBER_US    0xa1b2c3d4  // Magic number; timestamps in microseconds
#define PCAP_VERSION_MAJOR      2
#define PCAP_VERSION_MINOR      4

// .-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- struct PcapFileHeader -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
struct PcapFileHeader
{
    uint32_t  m_MagicNumber;        // Magic number
    uint16_t  m_VersionMajor;       // Major version number
    uint16_t  m_VersionMinor;       // Minor version number
    uint32_t  m_ThisZone;           // GMT to local correction; Always 0
    uint32_t  m_SigFigs;            // Accuracy of timestamps; Always 0
    uint32_t  m_SnapLen;            // Maximum length of captured packets, in bytes
    uint32_t  m_Network;            // Data link type
};

// .-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- struct PcapPckHeader -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
struct PcapPckHeader
{
    uint32_t  m_Seconds;            // Timestamp seconds
    uint32_t  m_MicroOrNanoSeconds; // Micro- or nanoseconds
    uint32_t  m_InclLen;            // Number of bytes saved in file
    uint32_t  m_OrigLen;            // Original length of packet
};

//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- struct IPHeader -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
typedef struct IPHeader 
{
    uint8_t     ihl:4;
    uint8_t     version:4;
    uint8_t     tos;
    uint16_t    tot_len;
    uint16_t    id;
    uint16_t    frag_off;
    uint8_t     ttl;
    uint8_t     protocol;
    uint16_t    check;
    uint32_t    saddr;
    uint32_t    daddr;
} IPHeader;

//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- struct UDPHeader -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
typedef struct UDPHeader 
{
    uint16_t    source;
    uint16_t    dest;
    uint16_t    len;
    uint16_t    check;
} UDPHeader;

//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- class NwUtils -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
class NwUtils
{  
public:
    static uint32_t ip_checksum2(const uint8_t* tab, int len, uint32_t sum);
    static uint16_t ip_checksum(const uint8_t* tab, int len, uint32_t sum);
    static int add_udp_headers2(uint8_t* buf, int payload_len,
                                uint32_t saddr, uint16_t sport,
                                uint32_t daddr, uint16_t dport);
};

//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- class CommandLineParams -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
//
class CommandLineParams
{
public:
    CommandLineParams();
    virtual ~CommandLineParams();

    void  Init();
    void  ParseCommandLine(int argc, char* argv[]);
    const char* Bandwidth2Str() const;
    const char* RxMode2Str() const;
    const char* ModType2Str() const;
    const char* QamJ83Annex2Str() const;
    const char* IpProtocol2Str() const;
    const char* IqDemodType2Str() const;
    const char* LnbVoltage2Str() const;
    const char* LnbTone2Str() const;
    const char * LnbBurst2Str() const;
    const char* DiseqcPortGroup2Str() const;

    //---- Application parameters ----

    char  m_FileName[256];      // Name of play file

    int  m_DvcType;             // -t: Type of device 
    int  m_DvcNum;              // -n: Device number
    int  m_Port;                // -i: Port index

    int  m_RxMode;              // -m: Receive mode
    bool  m_RxModeHuffman;      // -c: Enable Huffman compression
    int  m_SdiSubValue;         // Subvalue for SDI, determined from -m: Receive mode
    __int64  m_MaxSize;         // -x: Transmission rate

    int  m_ModType;             // -mt: Master modulation type
    double  m_CarrierFreq;      // -mf: carrier frequency
    int  m_QamJ83Annex;         // -ma: J83 annex (QAM-A/B/C)
    int  m_SymbolRate;          // -ms: Symbol rate for QAM-A/B/C and DVBS2
    int  m_Bandwidth;           // -mb: bandwidth
    int  m_NumberOfSegments;    // -mn: ISDB-T Number of Segments
    int  m_SubChannelNumber;    // -mc: ISDB-T Sub channel number, 0..41, default= 22
    int  m_StreamId;            // -mi: DVBS2 stream Id, 0..255, default= 0
    bool  m_LogMer;             // -mer: Log MER once per second

    int  m_LnbVoltage;          // -lnbv: LNB voltage (disable, 13V or 18V)
    bool  m_LnbToneEnable;      // -lnbt: Enable 22kHz tone
    int  m_LnbBurst;            // -lnbb: Tone burst (A or B)

    int  m_DiseqcPortGroup;     // -diseqcpg: DiSEqC portgroup

    DtIpPars  m_IpPars;         // IP parameters.
                                // -ipa: IP address and IP port
                                // -ipp: IP protocol

    int  m_IqDemodType;         // IQ demodulation type
    int  m_IqBandwidth;         // IQ signal bandwidth (in Hz)
    int  m_IqSampleRate;        // IQ sample rate (in Hz)

    int m_Polarity;             // -pc: Polarity Control

    bool  m_SilentMode;         // -s: Enable silent mode (i.e. no printf)
    bool  m_ShowHelp;           // -?: show help

    bool  m_RecDtSdiFile;       // Record to a DTSDI file 
    bool  m_RecSdiFile;       // Record to a SDI file 

protected:

    void  ParseParam(char* pParam, bool Flag, bool First=false, bool Last=false);
    void  ParseParamFlag(char* pParam, bool First=false, bool Last=false);
    void  ParseParamNotFlag(char* pParam, bool First=false, bool Last=false);

    bool  m_Error;              // Error detected while parsing command line?
    bool  m_LastFlagReqsArg;    // Last flag requires an argument
    char*  m_pLastFlag;         // Last flag
};


//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- class Recorder -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
//
class Recorder
{
public:
    Recorder();
    virtual ~Recorder();

    //---- Public operations ----
    int Record(int argc, char* argv[]);

protected:

    //---- Internal operation ----
    void AttachToInput();
    void DisplayRecordInfo();
    void InitAdvDemodInput();
    void InitInput();
    void Log(const char* pMessage, bool IgnoreSilence=false);
    void LogF(const char* pMessage, ... );
    void LogMer();
    void WriteSdiHeaderToFile(int VidStd, int NumFrames, int FrameSize);
    void RecordFile();
    void RecordAdvDemodFile();
    static void WriteAtsc3AlpFunc(void* pOpaque, DtStreamSelPars& StreamSel, 
                                                const unsigned char* pData, int Length);
    void ShowHelp();

    CommandLineParams  m_CmdLineParams;

    DtDevice  m_DtDvc;              // Our device
    DtInpChannel  m_DtInp;          // Our input channel
    DtAdvDemod  m_AdvDemod;         // Our advanced demodulation channel for ATSC 3.0
    bool  m_IsUsingAdvDemod;        // Is using advanced demodulation
    bool  m_Demod;                  // Current input is a demodulator
    bool  m_IqMonitor;              // Current input is Iq sample monitor
    bool  m_Ip;                     // Current input is a IP port
    bool  m_Lnb;                    // Current input supports LNB
    FILE*  m_pFile;                 // Our record file

    char*  m_pBuf;                  // Our data buffer
    __int64  m_NumBytesStored;      // Number bytes stored in file
    int  m_Align;                   // Alignment for record file (i.e. file should be
                                    // multiple of alignment)
    int  m_NumFramesStored;         // Number of frames stored in file
    int  m_FrameSize;               // Size of frames
};

#endif // #ifndef __DTRECORD_H
